package com.idenger.modules.edu.mobileWeb.pay;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.idenger.modules.edu.entity.common.BaseResponseMsg;
import com.idenger.modules.edu.entity.common.ResponseMsg;
import com.idenger.modules.edu.web.comm.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.idenger.common.utils.StringUtils;
import com.idenger.modules.edu.entity.enroll.EduEnroll;
import com.idenger.modules.edu.entity.income.EduIncome;
import com.idenger.modules.edu.entity.order.EduOrder;
import com.idenger.modules.edu.entity.user.EduUser;
import com.idenger.modules.edu.service.enroll.EduEnrollService;
import com.idenger.modules.edu.service.income.EduIncomeService;
import com.idenger.modules.edu.service.order.EduOrderService;
import com.idenger.modules.edu.service.shopping.EduShoppingCartService;
import com.idenger.modules.edu.service.user.EduUserService;
import com.idenger.modules.edu.web.utils.PayController;

import weixin.popular.api.PayMchAPI;
import weixin.popular.bean.paymch.MchBaseResult;
import weixin.popular.bean.paymch.MchPayNotify;
import weixin.popular.bean.paymch.Unifiedorder;
import weixin.popular.bean.paymch.UnifiedorderResult;
import weixin.popular.support.ExpireKey;
import weixin.popular.support.expirekey.DefaultExpireKey;
import weixin.popular.util.PayUtil;
import weixin.popular.util.SignatureUtil;
import weixin.popular.util.StreamUtils;
import weixin.popular.util.XMLConverUtil;

@Controller
@RequestMapping(value = "${mobilePath}/edu/pay/eduPay")
public class MPayController extends PayController{
	
	@Autowired
	private EduOrderService eduOrderService;
	@Autowired
	private EduUserService eduUserService;
	@Autowired
	private EduIncomeService eduIncomeService;
	@Autowired
	private EduEnrollService eduEnrollService;
	@Autowired
	private EduShoppingCartService eduShoppingCartService;

	//重复通知过滤
	private static ExpireKey expireKey = new DefaultExpireKey();
	
	
	@RequestMapping(value = "pay")
	public String pay(EduOrder eduOrder, HttpServletRequest request, HttpServletResponse response, Model model){
		BaseResponseMsg baseResponseMsg;
		EduUser currentUser = (EduUser) request.getAttribute("currentUser");
		EduUser eduUser = eduUserService.get(currentUser.getId());
		EduOrder eduOrder2 = eduOrderService.get(eduOrder.getId());
		//计算 price
        BigDecimal  price = new BigDecimal(eduOrder2.getPrice());
        BigDecimal  multiplier = new BigDecimal("100");
        price =  price.setScale(2,BigDecimal.ROUND_HALF_DOWN);
        price = price.multiply(multiplier);
        price = price.setScale(0, BigDecimal.ROUND_HALF_DOWN);
        String test_price= "1";
		if(eduOrder2 == null){
			baseResponseMsg = new BaseResponseMsg(new ResponseMsg("1", "error"));
			baseResponseMsg.addData("该订单不存在");
			return renderString(response, baseResponseMsg);
		}
		String body =eduOrder2.getOrderName();//课程名称或者项目名称
		Map paypara = packagePayPara(eduUser.getOpenid(),body,eduOrder2.getTradeNo(), request.getRemoteAddr(),test_price.toString());
		try {
			String json =readyPay(paypara);
			if(StringUtils.isNotBlank(json)){
				baseResponseMsg = new BaseResponseMsg(new ResponseMsg("0", "success"));
				baseResponseMsg.addData(json);
				return renderString(response, baseResponseMsg);
			}
		} catch (Exception e) {
			e.printStackTrace();
			baseResponseMsg = new BaseResponseMsg(new ResponseMsg("1", "error"));
			baseResponseMsg.addData("支付失败");
			return renderString(response, baseResponseMsg);
		}
		baseResponseMsg = new BaseResponseMsg(new ResponseMsg("1", "error"));
		baseResponseMsg.addData("支付失败");
		return renderString(response, baseResponseMsg);
	}


	
	@RequestMapping(value = "result")
	public void result(HttpServletRequest request, HttpServletResponse response, Model model)throws IOException {

		//获取请求数据
		String xmlData = StreamUtils.copyToString(request.getInputStream(), Charset.forName("utf-8"));
		//将XML转为MAP,确保所有字段都参与签名验证
		Map<String,String> mapData = XMLConverUtil.convertToMap(xmlData);
		//转换数据对象
		MchPayNotify payNotify = XMLConverUtil.convertToObject(MchPayNotify.class,xmlData);
		//已处理 去重
		if(expireKey.exists(payNotify.getTransaction_id())){
			MchBaseResult baseResult = new MchBaseResult();
			baseResult.setReturn_code("SUCCESS");
			baseResult.setReturn_msg("OK");
			response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
			return ;
		}
		//签名验证
		if(SignatureUtil.validateSign(mapData,wxSecretKey)){
			payNotify.buildDynamicField(mapData);
			//回调成功主逻辑
			paySucessLogic(payNotify.getOut_trade_no(),payNotify.getOpenid(),xmlData);
			expireKey.add(payNotify.getTransaction_id());
			MchBaseResult baseResult = new MchBaseResult();
			baseResult.setReturn_code("SUCCESS");
			baseResult.setReturn_msg("OK");
			response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
		}else{
			//回调失败主逻辑
			MchBaseResult baseResult = new MchBaseResult();
			baseResult.setReturn_code("FAIL");
			baseResult.setReturn_msg("ERROR");
			response.getOutputStream().write(XMLConverUtil.convertToXML(baseResult).getBytes());
		}

	}

	/**
	 * 拼装支付参数
	 * @param openId
	 * @param payBody
	 * @param tradeNo
	 * @param ip
	 * @param price
	 * @return
	 */
	private Map packagePayPara(String openId,String payBody,String tradeNo,String ip,String price){
		Map<String,String> para = new HashMap<>();
		para.put("appid",wxAppId);
		para.put("mch_id",wxMchId);
		para.put("pay_key",wxSecretKey);
		para.put("notify_url",wxNotifyUrl);
		para.put("wx_openid",openId);
		para.put("pay_body",payBody);
		para.put("trade_no",tradeNo);
		para.put("ip",ip);
		para.put("price",price);
		return para;

	}

	/**
	 * 预支付逻辑
	 * @param para
	 * @return
	 */
	private String readyPay(Map<String,String> para){
		for(Entry<String, String> entry : para.entrySet()){  
		    System.out.print("Key = "+entry.getKey()+",value="+entry.getValue());  
		}  
		String json = "";
		Unifiedorder unifiedorder = new Unifiedorder();
		unifiedorder.setAppid(para.get("appid"));
		unifiedorder.setMch_id(para.get("mch_id"));
		unifiedorder.setNonce_str(UUID.randomUUID().toString().toString().replace("-", ""));
		unifiedorder.setOpenid(para.get("wx_openid"));
		unifiedorder.setBody(para.get("pay_body"));
		unifiedorder.setOut_trade_no(para.get("trade_no"));
		unifiedorder.setTotal_fee(para.get("price"));//单位分
		unifiedorder.setSpbill_create_ip(para.get("ip"));//IP
		unifiedorder.setNotify_url(para.get("notify_url"));
		unifiedorder.setTrade_type("JSAPI");//JSAPI，NATIVE，APP，WAP
		//统一下单，生成预支付订单
		UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder,para.get("pay_key"));
		if(unifiedorderResult.getSign_status() !=null && unifiedorderResult.getSign_status()){
			json = PayUtil.generateMchPayJsRequestJson(unifiedorderResult.getPrepay_id(), para.get("appid"), para.get("pay_key"));
			return json;
		}
		return json;

	}

	/**
	 * 回调成功逻辑 需要再一个事物里面操作
	 * @param tradeNo
	 * @param openid
	 * @param resultXml
	 */

	private void paySucessLogic(String tradeNo,String openid,String resultXml){
		//回调成功
		EduOrder eduOrder = eduOrderService.findOrderByTradeNo(tradeNo);
		eduOrder.setRemarks(resultXml);
		eduOrder.setOrderStatus(Constant.ORDER_STATUS_COMPLETED);
		eduOrder.setPayStatus(Constant.ORDER_PAYSTATUS_ALREADYPAY);
		eduOrderService.save(eduOrder);
		EduIncome eduIncome = new EduIncome();
		eduIncome.setUserid(eduOrder.getUserid());
		eduIncome.setPayDate(new Date());
		eduIncome.setMoney(eduOrder.getPrice());
		eduIncome.setSource(Constant.INCOME_DICT_SOURCE);
		eduIncome.setStatus(Constant.INCOME_STATUS_NORMAL);
		eduIncome.setBusinessid(eduOrder.getId());
		eduIncome.setIDesc(Constant.INCOME_DICT_DESC);
		eduIncome.setPaymethod(eduOrder.getPayMethod());
		eduIncomeService.save(eduIncome);
		deleteShoppCart(eduOrder.getId(), eduOrder.getUserid());
	}
	
	/***
	 * 删除购物车里的记录
	 * @param orderId
	 * @param userId
	 */
    private  void deleteShoppCart(String orderId,String userId){
		List<EduEnroll> list = eduEnrollService.findListForOrderId(orderId);
			for(EduEnroll eduEnroll :list){
				eduShoppingCartService.deleteShoppoCart(userId, eduEnroll.getCurriculumId());
			}
    }
}
